#include "stdafx.h"
#include "state_machine.h"
#include "xml_tree.h"
#include "attr_tree.h"
using namespace ui;
using namespace std;

StateMachine* gStateMachine = nullptr;

bool IStateReceiver::NotifyMaker(std::shared_ptr<StateEvent> event)
{
	return gStateMachine->NotifyMaker(event);
}

bool IStateMaker::NotifyReceiver(std::shared_ptr<StateEvent> event)
{
	return gStateMachine->NotifyReceiver(event);
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

bool StateMachine::InsertReceiver(IStateReceiver* receiver)
{
	assert(receiver && std::find(m_vecAcceptor.begin(), m_vecAcceptor.end(), receiver) == m_vecAcceptor.end());
	if (receiver && std::find(m_vecAcceptor.begin(), m_vecAcceptor.end(), receiver) == m_vecAcceptor.end())
	{
		m_vecAcceptor.push_back(receiver);
		return true;
	}
	return false;
}

bool StateMachine::InsertMaker(IStateMaker* maker)
{
	assert(!m_coreMaker);
	m_coreMaker = maker;
	return true;
}

bool StateMachine::NotifyMaker(std::shared_ptr<StateEvent> event)
{
	return m_coreMaker->MakeStateEvent(event);
}

bool StateMachine::NotifyReceiver(std::shared_ptr<StateEvent> event)
{
	assert(m_currVersion < (int)m_vecHistoryEvent.size());
	if (m_currVersion != -1 && m_currVersion < m_vecHistoryEvent.size() - 1)
	{
		m_vecHistoryEvent.erase(m_vecHistoryEvent.begin() + (m_currVersion + 1), m_vecHistoryEvent.end());
	}
	m_vecHistoryEvent.push_back(event);
	m_currVersion++;
	assert(m_currVersion == m_vecHistoryEvent.size() - 1);
	for (IStateReceiver* receiver : m_vecAcceptor)
	{
		if (receiver != event->from)
		{
			receiver->DoStateEvent(event);
		}
	}
	return true;
}

bool StateMachine::Rollback()
{
	if (m_currVersion >= 0)
	{
		m_currVersion--;
	}
	return true;
}
bool StateMachine::RollTo(int version)
{
	if (version == m_currVersion)
		return false;
	if (version < m_vecHistoryEvent.size())
	{
		m_currVersion = version;
	}
	return true;
}

